﻿//Created by Action Script Viewer - http://www.buraks.com/asv
package Classes.actions {
    import Engine.Classes.*;
    import Engine.Helpers.*;
    import Classes.*;
    import Classes.sim.*;
    import Modules.stats.experiments.*;
    import Engine.*;

    public class ActionNavigate extends NPCAction {

        protected static const V_UP:Vector3 = new Vector3(0, 0, 1);

        protected var m_roadSize:Number;
        protected var m_source:MapResource;
        protected var m_target:MapResource;
        protected var m_path:Array;
        protected var m_startRightTurn:Boolean = false;
        protected var m_endRightTurn:Boolean = false;
        protected var m_offset:Number;
        protected var m_graph:RoadGraph;
        protected var m_fallbackAction:BaseAction;
        protected var m_teleportOnFailure:Boolean = false;
        protected var m_navigationFailed:Boolean = false;
        protected var m_pathTime:Number = 0;
        protected var m_velocityWalk:Number = 0;
        protected var m_pathType:int = 1;

        public function ActionNavigate(_arg1:NPC, _arg2:MapResource, _arg3:MapResource){
            super(_arg1);
            this.m_source = _arg3;
            this.m_target = _arg2;
            this.m_roadSize = Global.world.citySim.roadManager.getRoadSize().x;
            this.m_offset = ((_arg1.roadOffset * this.m_roadSize) * (_arg1.isRightSideNav) ? 1 : -1);
            if ((_arg1 is Vehicle)){
                this.m_pathType = RoadManager.PATH_ROAD_ONLY;
            };
            this.m_velocityWalk = _arg1.velocityWalk;
        }
        public static function getMovementDirection(_arg1:Vector3, _arg2:Number=0):int{
            if (Math.abs(_arg1.x) > Math.abs(_arg1.y)){
                if (_arg1.x > _arg2){
                    return (Constants.DIRECTION_NE);
                };
                if (_arg1.x < -(_arg2)){
                    return (Constants.DIRECTION_SW);
                };
            } else {
                if (_arg1.y > _arg2){
                    return (Constants.DIRECTION_NW);
                };
                if (_arg1.y < -(_arg2)){
                    return (Constants.DIRECTION_SE);
                };
            };
            return (Constants.DIRECTION_MAX);
        }

        public function setFallbackAction(_arg1:BaseAction):ActionNavigate{
            this.m_fallbackAction = _arg1;
            return (this);
        }
        public function setTeleportOnFailure(_arg1:Boolean):ActionNavigate{
            this.m_teleportOnFailure = _arg1;
            return (this);
        }
        public function setPathType(_arg1:int):ActionNavigate{
            this.m_pathType = _arg1;
            return (this);
        }
        protected function get navigationVelocity():Number{
            return (this.m_velocityWalk);
        }
        public function get graph():RoadGraph{
            return (this.m_graph);
        }
        public function get target():MapResource{
            return (this.m_target);
        }
        override public function update(_arg1:Number):void{
            var _local7:PathElement;
            var _local8:Vector3;
            var _local9:Vector3;
            if (_arg1 > 0.5){
                _arg1 = 0.5;
            };
            if (((!(this.m_path)) || ((this.m_path.length == 0)))){
                if (this.m_navigationFailed){
                    this.doNavigationFailed();
                };
                m_npc.getStateMachine().removeState(this);
                return;
            };
            if (Global.world.citySim.roadManager.isShowingOverlay){
                m_npc.m_navDbgPath = this.m_path;
            } else {
                m_npc.m_navDbgPath = null;
            };
            this.m_pathTime = (this.m_pathTime - _arg1);
            var _local2:Number = (_arg1 * this.navigationVelocity);
            var _local3:Boolean;
            do  {
                _local7 = this.m_path[0];
                _local8 = _local7.offsetPosition;
                _local9 = _local8.subtract(m_npc.getPosition());
                _local3 = (_local9.length() > _local2);
                if (!_local3){
                    m_npc.setPosition(_local8.x, _local8.y, _local8.z);
                    _local2 = (_local2 - _local9.length());
                    this.m_path.shift();
                    this.maybePerformAmbientAction();
                };
                if (this.m_path.length == 0){
                    _local3 = true;
                };
            } while (!(_local3));
            var _local4:Vector3 = ((_local9.length())>0) ? _local9.normalize().scale(_local2) : new Vector3(0, 0, 0);
            var _local5:Vector3 = m_npc.getPosition().add(_local4);
            m_npc.setPosition(_local5.x, _local5.y, _local5.z);
            var _local6:int = getMovementDirection(_local9);
            if (_local6 != m_npc.getDirection()){
                if ((m_npc is Vehicle)){
                    (m_npc as Vehicle).startTurnAnimation(_local6);
                } else {
                    m_npc.setDirection(_local6);
                    m_npc.setState(m_npc.getState());
                };
            };
            m_npc.conditionallyReattach();
        }
        protected function updatePath(_arg1:Boolean):void{
            var _local4:Array;
            var _local5:WorldObject;
            var _local6:Box3D;
            var _local2:Vector3 = m_npc.getPosition();
            if ((((this.m_source == null)) || (_arg1))){
                _local4 = Global.world.getCollisionMap().getObjectsByPosition(_local2.x, _local2.y);
                for each (_local5 in _local4) {
                    if ((_local5 is MapResource)){
                        this.m_source = (_local5 as MapResource);
                        break;
                    };
                };
            };
            if (this.m_source == null){
                _local6 = new Box3D(new Vector3((_local2.x - 1), (_local2.y - 1)), new Vector3(2, 2));
                _local4 = Global.world.getCollisionMap().getIntersectingObjects(_local6);
                for each (_local5 in _local4) {
                    if ((_local5 is MapResource)){
                        this.m_source = (_local5 as MapResource);
                        break;
                    };
                };
            };
            var _local3:Object;
            if (m_npc.alwaysCulled){
                if (Global.experimentManager.inPerfExperiment(ExperimentDefinitions.EXPERIMENT_OPTIMIZE_FRAMERATE, ExperimentDefinitions.EXPERIMENT_OPTIMIZE_INVISIBLE_NPCS)){
                    _local3 = Global.world.citySim.roadManager.createInvisiblePeepPath(this.m_source, this.m_target);
                };
            };
            if (_local3 == null){
                _local3 = Global.world.citySim.roadManager.findPath(this.m_source, this.m_target, this.m_pathType);
            };
            if (_local3 == null){
                _local3 = {
                    path:[new PathElement(m_npc.getPosition())],
                    graph:null
                };
                this.m_navigationFailed = true;
            };
            m_npc.m_navRandom = false;
            m_npc.m_navDbgPath2 = null;
            this.m_graph = _local3.graph;
            this.m_path = this.makeOffsetPath(_local3.path, null, !(m_npc.isVehicle));
            this.debugPrintPath();
            this.doPathCleanup();
            this.computeTimeToDestination();
        }
        private function adjustEndpoints(_arg1:Boolean, _arg2:Vector3, _arg3:Vector3, _arg4:Vector3):Vector3{
            var _local5:Number = this.m_roadSize;
            if (_arg1){
                if (_arg3.x == _arg4.x){
                    if (Math.abs((_arg3.y - _arg2.y)) < _local5){
                        _arg3.y = _arg2.y;
                    };
                } else {
                    if (_arg3.y == _arg4.y){
                        if (Math.abs((_arg3.x - _arg2.x)) < _local5){
                            _arg3.x = _arg2.x;
                        };
                    };
                };
            } else {
                if (_arg3.x == _arg2.x){
                    if (Math.abs((_arg3.y - _arg4.y)) < _local5){
                        _arg3.y = _arg4.y;
                    };
                } else {
                    if (_arg3.y == _arg2.y){
                        if (Math.abs((_arg3.x - _arg4.x)) < _local5){
                            _arg3.x = _arg4.x;
                        };
                    };
                };
            };
            return (_arg3);
        }
        private function checkEndpointTurns(_arg1:Array):void{
            var _local9:Vector3;
            var _local10:PathElement;
            var _local11:Vector3;
            this.m_startRightTurn = false;
            this.m_endRightTurn = false;
            var _local2:int;
            var _local3:PathElement = (_arg1[_local2] as PathElement);
            var _local4:Vector3 = _local3.basePosition;
            var _local5:Vector3 = _local4;
            var _local6:Vector3 = _local4;
            var _local7:Boolean;
            var _local8:Boolean;
            while (_local2 < (_arg1.length - 1)) {
                _local10 = (_arg1[(_local2 + 1)] as PathElement);
                _local6 = _local10.basePosition;
                _local11 = _local6.subtract(_local4);
                if (((((!(_local8)) && (_local7))) && ((_local3.type == PathElement.TYPE_ROAD)))){
                    _local9 = _local4.subtract(_local5).cross(_local6.subtract(_local4));
                    this.m_startRightTurn = (_local9.z < 0);
                    _local8 = true;
                };
                if (((((_local8) && ((((_local2 == (_arg1.length - 2))) || ((_local10.type == PathElement.TYPE_NONROAD)))))) && (_local7))){
                    _local9 = _local4.subtract(_local5).cross(_local6.subtract(_local4));
                    this.m_endRightTurn = (_local9.z < 0);
                    break;
                };
                if (_local4 != _local6){
                    _local5 = _local4;
                    _local7 = true;
                    _local4 = _local6;
                    _local3 = _local10;
                };
                _local2++;
            };
        }
        protected function makeOffsetPath(_arg1:Array, _arg2:Vector3, _arg3:Boolean):Array{
            var _local12:PathElement;
            var _local13:Vector3;
            var _local14:Vector3;
            var _local15:Number;
            var _local16:Vector3;
            var _local17:Boolean;
            var _local4:Array = [];
            if (_arg1.length < 3){
                return (_arg1);
            };
            var _local5:Vector3 = _arg2;
            if (_arg2 == null){
                _local5 = (_arg1[1] as PathElement).basePosition.subtract((_arg1[0] as PathElement).basePosition);
            };
            if (_arg3){
                this.checkEndpointTurns(_arg1);
                if ((((this.m_offset < 0)) && (this.m_startRightTurn))){
                    this.m_offset = (this.m_offset * -1);
                };
                if ((((this.m_offset > 0)) && (!(this.m_startRightTurn)))){
                    this.m_offset = (this.m_offset * -1);
                };
            };
            var _local6:int;
            var _local7:PathElement = (_arg1[_local6] as PathElement);
            var _local8:Vector3 = _local7.basePosition;
            var _local9:Vector3 = _local8;
            var _local10:Vector3 = _local5;
            var _local11:Boolean = _arg3;
            while (_local6 < (_arg1.length - 1)) {
                _local12 = (_arg1[(_local6 + 1)] as PathElement);
                _local13 = _local12.basePosition;
                _local14 = _local13.subtract(_local8);
                if (_local14.length() > 0){
                    if (_local5.length() == 0){
                        _local5 = _local14;
                    };
                    if ((((((_local4.length == 1)) || ((_local6 == (_arg1.length - 2))))) && (_arg3))){
                        _local8 = this.adjustEndpoints((_local4.length == 1), _local9, _local8, _local13);
                    };
                    _local15 = _local5.dot(_local14);
                    if ((((_local6 == 0)) && (_arg3))){
                        _local4.push(_local7);
                    } else {
                        if (_local7.type == PathElement.TYPE_NONROAD){
                            _local4.push(_local7);
                        } else {
                            if ((((_local4.length == 1)) && (_arg3))){
                                _local4.push(this.getOffsetPoint(_local8, _local14, this.m_offset, 0));
                            } else {
                                if ((((_local12.type == PathElement.TYPE_NONROAD)) && (!(m_npc.isVehicle)))){
                                    _local4.push(this.getOffsetPoint(_local8, _local5, this.m_offset, 0));
                                } else {
                                    if (_local15 != 0){
                                        if (_local15 > 0){
                                            if (_local11){
                                                _local4.push(this.getOffsetPoint(_local8, _local14, this.m_offset, 0));
                                            } else {
                                                _local4.push(this.getOffsetPoint(_local8, _local5, this.m_offset, 0));
                                            };
                                            if (((_arg3) && (!((this.m_startRightTurn == this.m_endRightTurn))))){
                                                this.m_offset = (this.m_offset * -1);
                                                if (_local11){
                                                    _local4.push(this.getOffsetPoint(_local8, _local14, this.m_offset, 0));
                                                } else {
                                                    _local4.push(this.getOffsetPoint(_local8, _local5, this.m_offset, 0));
                                                };
                                                this.m_startRightTurn = this.m_endRightTurn;
                                            };
                                        } else {
                                            _local4.push(this.getOffsetPoint(_local8, _local5, this.m_offset, this.m_offset));
                                            _local4.push(this.getOffsetPoint(_local8, _local5.scale(-1), this.m_offset, -(this.m_offset)));
                                        };
                                    } else {
                                        _local16 = _local5.cross(_local14);
                                        _local17 = (_local16.z > 0);
                                        _local4.push(this.getOffsetPoint(_local8, _local5, this.m_offset, (_local17) ? this.m_offset : -(this.m_offset)));
                                    };
                                };
                            };
                        };
                    };
                    _local11 = (_local7.type == PathElement.TYPE_NONROAD);
                    _local10 = _local5;
                    _local9 = _local8;
                    _local7 = _local12;
                    _local8 = _local13;
                    _local5 = _local14;
                };
                _local6++;
            };
            if (!m_npc.isVehicle){
                _local4.push((_arg1[(_arg1.length - 1)] as PathElement));
            } else {
                _local4.push(this.getOffsetPoint(_local8, _local5, this.m_offset, 0));
            };
            return (_local4);
        }
        protected function doPathCleanup():void{
            var _local1:int;
            var _local2:Vector3;
            var _local3:Vector3;
            var _local4:int;
            var _local5:Vector3;
            var _local6:int;
            var _local7:int;
            var _local8:Vector3;
            var _local9:Vector3;
            var _local10:int;
            var _local11:int;
            var _local12:Vector3;
            var _local13:int;
            if (this.m_path.length >= 2){
                _local1 = 0;
                _local2 = m_npc.getPosition();
                _local3 = (this.m_path[0] as PathElement).offsetPosition.subtract(_local2);
                _local4 = 1;
                while (_local4 < this.m_path.length) {
                    _local5 = (this.m_path[_local4] as PathElement).offsetPosition.subtract(_local2);
                    if (_local3.length() > _local5.length()){
                        _local1 = _local4;
                    };
                    _local4++;
                };
                if (_local1 > 0){
                    this.m_path.splice(0, _local1);
                };
            };
            if (this.m_path.length >= 2){
                _local6 = (this.m_path.length - 1);
                _local7 = (this.m_path.length - 2);
                _local8 = (this.m_path[_local6] as PathElement).offsetPosition;
                _local9 = (this.m_path[_local7] as PathElement).offsetPosition.subtract(_local8);
                _local10 = 0;
                while (_local10 < (_local6 - 1)) {
                    _local12 = (this.m_path[_local10] as PathElement).offsetPosition.subtract(_local8);
                    if (_local12.length() < _local9.length()){
                        _local7 = _local10;
                    };
                    _local10++;
                };
                _local11 = (_local7 + 1);
                if (_local11 < _local6){
                    _local13 = (_local6 - _local11);
                    this.m_path.splice(_local11, _local13);
                };
            };
        }
        protected function getOffsetPoint(_arg1:Vector3, _arg2:Vector3, _arg3:Number, _arg4:Number, _arg5:int=0):PathElement{
            var _local6:Vector3 = _arg2.cross(V_UP).normalize().scale(_arg3);
            var _local7:Vector3 = _arg1.add(_local6);
            if (_arg4 != 0){
                _local7 = _local7.add(_arg2.normalize().scale(_arg4));
            };
            return (new PathElement(_arg1, _local7, _arg5));
        }
        protected function doNavigationFailed():void{
            var _local1:Vector3;
            if (this.m_teleportOnFailure){
                _local1 = this.m_target.getHotspot();
                m_npc.setPosition(_local1.x, _local1.y);
            };
            if (this.m_fallbackAction){
                m_npc.getStateMachine().removeAllStates();
                m_npc.getStateMachine().addActions(this.m_fallbackAction);
            };
        }
        protected function maybePerformAmbientAction():void{
            var _local1:Number = GlobalEngine.getTimer();
            if (((m_npc.performsAmbientActions) && ((m_npc.nextAmbientActionStart < _local1)))){
                m_npc.getStateMachine().addState(this.makeAmbientAction());
                m_npc.randomizeNextAmbientActionStart();
            };
        }
        protected function makeAmbientAction():NPCAction{
            return (new ActionPlayAnimation(m_npc, "idle", 3));
        }
        protected function debugPrintPath():void{
        }
        override public function enter():void{
            var _local1:PathElement;
            var _local2:Vector3;
            var _local3:int;
            var _local4:Vehicle;
            super.enter();
            this.updatePath(false);
            if ((((((((m_npc is Vehicle)) && (this.m_path))) && ((this.m_path.length > 1)))) && (!((this.m_path[1] == null))))){
                _local1 = (this.m_path[1] as PathElement);
                _local2 = _local1.basePosition.subtract(m_npc.getPosition());
                _local3 = getMovementDirection(_local2);
                m_npc.setDirection(_local3);
                m_npc.setState(m_npc.getState());
                _local4 = (m_npc as Vehicle);
                _local4.startTurnAnimation(_local3);
            };
        }
        override public function reenter():void{
            super.reenter();
            this.updatePath(true);
        }
        protected function computeTimeToDestination():void{
            this.m_pathTime = ((Global.world.citySim.roadManager.getRoadSize().x * (this.m_path.length - 1)) / this.navigationVelocity);
        }
        public function getSecondsLeft():Number{
            return (this.m_pathTime);
        }

    }
}//package Classes.actions 
